// Test both definining static members, and referring to an object's other static members, in companion object and non-companion object contexts.
// For the companion object all the references to other properties and methods should extract as ordinary instance calls and field read and writes,
// but those methods / getters / setters that are annotated static should get an additional static proxy method defined on the surrounding class--
// for example, we should see (using Java notation) public static String HasCompanion.staticMethod(String s) { return Companion.staticMethod(s); }.
// For the non-companion object, the static-annotated methods should themselves be extracted as static members, and calls / gets / sets that use them
// should extract as static calls. Static members using non-static ones should extract like staticMethod(...) { INSTANCE.nonStaticMethod(...) },
// where the reference to INSTANCE replaces what would normally be a `this` reference.

public class HasCompanion {

  companion object {

    @JvmStatic fun staticMethod(s: String): String = nonStaticMethod(s)
    fun nonStaticMethod(s: String): String = staticMethod(s)

    @JvmStatic var staticProp: String = "a"
    var nonStaticProp: String = "b"

    var propWithStaticGetter: String
      @JvmStatic get() = propWithStaticSetter
      set(s: String) { propWithStaticSetter = s }
      
    var propWithStaticSetter: String
      get() = propWithStaticGetter
      @JvmStatic set(s: String) { propWithStaticGetter = s }

  }

}

object NonCompanion {

  @JvmStatic fun staticMethod(s: String): String = nonStaticMethod(s)
  fun nonStaticMethod(s: String): String = staticMethod(s)
      
  @JvmStatic var staticProp: String = "a"
  var nonStaticProp: String = "b"
      
  var propWithStaticGetter: String
    @JvmStatic get() = propWithStaticSetter
    set(s: String) { propWithStaticSetter = s }
      
  var propWithStaticSetter: String
    get() = propWithStaticGetter
    @JvmStatic set(s: String) { propWithStaticGetter = s }

}

fun externalUser() {

  // These all extract as instance calls (to HasCompanion.Companion), since a Kotlin caller won't use the static proxy methods generated by the @JvmStatic annotation.
  HasCompanion.staticMethod("1")
  HasCompanion.nonStaticMethod("2")
  HasCompanion.staticProp = HasCompanion.nonStaticProp
  HasCompanion.nonStaticProp = HasCompanion.staticProp
  HasCompanion.propWithStaticGetter = HasCompanion.propWithStaticSetter
  HasCompanion.propWithStaticSetter = HasCompanion.propWithStaticGetter
  
  // These extract as static methods, since there is no proxy method in the non-companion object case.
  NonCompanion.staticMethod("1")
  NonCompanion.nonStaticMethod("2")
  NonCompanion.staticProp = NonCompanion.nonStaticProp
  NonCompanion.nonStaticProp = NonCompanion.staticProp
  NonCompanion.propWithStaticGetter = NonCompanion.propWithStaticSetter
  NonCompanion.propWithStaticSetter = NonCompanion.propWithStaticGetter

}
